import { UILayerConfig } from "../../Config/Config";
import BaseUI from "../BaseUI";
import ResLoader from "./ResLoader";

//UI界面 预制体映射
export interface UILayerDesc {
    scriptName: string, //脚本名
    prefabUrl: string,  //预制体路径
    bundleName?: string  //bundel路径
    type: LayerType, //类型
    loadingLayerName?:string //加载时用的loading界面
}

//ui层类型定义
export enum LayerType {
    Screen = 1,      //全屏显示UI
    Fixed = 2,      //固定UI组件, 可以显示多个
    Popup = 4,      //弹窗, 只能显示一个
    Toast = 8,      //消息提示
    Alone = 16,      //独立UI
}


class LayerManager {
    public static instance: LayerManager = new LayerManager();

    //layer缓存
    public cacheLayer = new Map<string, BaseUI>();

    //正在打开的layer缓存
    public openingLayerName = [];

    //根节点
    public root: cc.Node;

    //设置根节点
    public setRoot(root: cc.Node) {
        this.root = root;
    }

    //打开弹窗
    public async open(name: string, data?: any): Promise<BaseUI> {

        let layerDesc: UILayerDesc = UILayerConfig[name] || null;
        if (!layerDesc) {
            throw new Error("OpenUI[" + name + "] 不存在UI配置");
        }

        //检测是否正在打开中
        if(this.openingLayerName.includes(name)){
            return;
        }

        this.openingLayerName.push(name)

        let uiScript:BaseUI;
        if (this.cacheLayer.has(name)) {
            uiScript = this.cacheLayer.get(name)
        }

        //如果已加载且已显示
        if(uiScript && uiScript.node.active){
            console.log("layer" ,name,"已显示")
            return uiScript
        }

        //遮罩loading
        if(layerDesc.loadingLayerName){
            await this.open(layerDesc.loadingLayerName)
        }

        switch (UILayerConfig[name].type) {
            case LayerType.Screen:
                //关闭打开的场景
                let cacheLayerNames = Array.from(this.cacheLayer.keys());

                for(let k in cacheLayerNames ){
                    let n = cacheLayerNames[k]
                    if(UILayerConfig[n].type == LayerType.Screen && this.cacheLayer.get(n).node.active){
                        await this.close(n)
                    }
                }

                //未加载尝试加载
                if(!uiScript){
                    uiScript = await this.load(name,"Screen");
                }

                break;
            case LayerType.Fixed:
                break;
            case LayerType.Popup:
                break;
            case LayerType.Toast:
                break;
            case LayerType.Alone:
                if(!uiScript){
                    uiScript = await this.load(name,"Alone");
                }
                break;
        }

        uiScript.node.active = true;

        //关闭遮罩loading
        if(layerDesc.loadingLayerName){
            await this.close(layerDesc.loadingLayerName)
        }

        await uiScript.showEffect();
        await uiScript.onShow(data);


        //删除
        let index = this.openingLayerName.indexOf(name)
        if (index > -1) {
            this.openingLayerName.splice(index, 1);
        }

        return uiScript
    }




    //关闭弹窗
    public async close(name: string){
        if (!UILayerConfig[name]) {
            throw new Error("OpenUI[" + name + "] 不存在UI配置");
        }

        let uiScript = this.cacheLayer.get(name);
        if(!uiScript){
            return;
        }

        //显示效果
        await uiScript.hideEffect()
        await uiScript.onHide();
        uiScript.node.active = false;
        console.log("close",name)
    }

    public async remove(name: string): Promise<void> {
        if (!this.cacheLayer.has(name)) return;

        let uiScript = this.cacheLayer.get(name);

        //清除引用计数
        let perfabAsset:cc.Asset = uiScript.node["__asset__"];
        perfabAsset.decRef();

        uiScript.node.destroy();
        this.cacheLayer.delete(name)
    }

    //加载方法
    public async load( name: string,layerNodeName:string): Promise<BaseUI> {
        let uiConfig: UILayerDesc = UILayerConfig[name];

        let perfabNode = await ResLoader.load(uiConfig.prefabUrl, cc.Prefab, uiConfig.bundleName).then((asset: cc.Prefab) => {
            //引用计数
            asset.addRef();

            //初始化节点 并在节点上 设置当前资源
            let node:cc.Node =  cc.instantiate(asset);
            node["__asset__"] = asset

            return node
        })

        //默认不显示
        perfabNode.active = false;

        //获取加载脚本
        let uiScript: BaseUI = perfabNode.getComponent(uiConfig.scriptName)

        //将UI添加进缓存
        this.cacheLayer.set(name, uiScript)

        //添加节点到相关节点
        this.root.getChildByName(layerNodeName).addChild(perfabNode)

        return uiScript;
    }

}

export default LayerManager.instance